# -*- coding: utf-8 -*-
# 标准库导入
import sys,os,time,sqlite3
import subprocess
import platform
from threading import Thread
# 第三方库导入
from PyQt5.QtCore import Qt, pyqtSignal, QThread  # 修改：添加QThread导入
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
    QLabel, QLineEdit, QPushButton, QTableWidget, QTableWidgetItem,
    QHeaderView, QMessageBox, QStackedWidget, QComboBox, QFormLayout,
    QDialog, QDialogButtonBox, QStyleFactory, QGraphicsDropShadowEffect,
    QSizePolicy, QButtonGroup, QScrollArea, QFrame # 新增 QButtonGroup
)

from PyQt5.QtGui import QFont, QIcon, QPixmap, QColor, QDoubleValidator, QIntValidator
from tqsdk import TqApi, TqAuth, TqAccount, TqSim,TqKq

# 本地模块导入
# 修改导入语句
from database_utils_stable04_01 import (
    connect_db,
    get_all_products,
    insert_product,
    update_product,
    delete_product,
    get_monitored_products,
    delete_product_by_name,
    get_product_by_id
)
import asyncio
# from qasync import asyncSlot, QEventLoop
import psutil


class CapitalManager(QMainWindow):
    def __init__(self):
        super().__init__()
        self.thread = None  # 新增线程引用
        # 新增线程终止标志
        self._shutting_down = False
        self.init_data()  # 这个调用已经存在
        self.init_ui()
        self.setup_connections()
        self.setWindowTitle("致远滚动迭代量化交易工作室 Ver4.0 QQ群：933538038")
        self.resize(1500, 1000)
        self.handle_page_change(0)
        self.process_id = None
        self.worker_thread=None
        self.connect_tq() #启动时，自动连接天勤账户
        self.exe_path=None
        self.changed_items=set()
        #print("changed_items initialized:", self.changed_items)  # 添加打印语句


    # 添加缺失的信号定义
    update_signal = pyqtSignal(str)
    connection_signal = pyqtSignal(str, bool)


    def update_capital(self):
        """更新账户资金线程"""
        tm=time.time()
        while time.time() > tm:
            tm=time.time()+60
            try:
                # 添加更完善的账户验证
                while self.api is None:
                    QMessageBox.critical(self, "错误", "未连接到天勤账户")
                
                # 主动查询账户信息（关键修复）
                account = self.api.get_account()
                _last_available=0.0
                while True:
                    if account.available != _last_available:
                        self.update_signal.emit(f"{account.available:.2f}")
                        _last_available = account.available
            except Exception as e:
                print(f"更新异常: {str(e)}")




    def connect_tq(self):
        def connect_tq_worker():
            try:
                #快期模拟账户
                tq_kq = TqKq()
                self.api = TqApi(account=tq_kq, auth=TqAuth("cps168", "alibaba"))
                self.macc=self.api.get_account()


                #连接超时处理
                timeout = time.time() + 60  # 延长至20秒
                while not self.api or not self.macc:
                    self.connect_btn.setEnabled(False)
                    self.connect_btn.setText("连接中...")
                    if time.time() > timeout:
                        raise TimeoutError("连接超时")

                if self.api and self.macc:
                    print("已经成功连接天勤账户")
                    print("当前账户可用资金：",self.macc.available)
                    
                    # 修正f-string语法错误
                    self.update_signal.emit(f"{self.macc.available:.2f}")  # 新增
                    
                    # 发射连接成功信号
                    self.connection_signal.emit("已连接 (点击断开)", True)

                    # 启动资金更新线程
                    Thread(target=self.update_capital,daemon=True).start()

                
            except Exception as e:
                self.connection_signal.emit(f"连接失败: {str(e)}", False)
        # 启动连接线程,用于避免阻塞主线程
        Thread(target=connect_tq_worker, daemon=True).start()


     
    def handle_connection(self, text, success):
        """处理连接状态更新"""
        self.connect_btn.setText(text)
        self.connect_btn.setEnabled(True)  # 确保按钮始终可点击
        if success:
            try:
                self.connect_btn.clicked.disconnect()
            except TypeError:
                pass
            # 修改为直接绑定无需lambda
            self.connect_btn.clicked.connect(self.disconnect_tq)
        else:
            try:
                self.connect_btn.clicked.disconnect()
            except TypeError:
                pass
            self.connect_btn.clicked.connect(self.connect_tq)
        QApplication.processEvents()


    def disconnect_tq(self):         
        """断开天勤账户连接"""
        try:
            if self.api:
                # 等待最后一次更新完成
                # while self.api.register_update_notify():
                #     pass
                # 在主线程执行关闭操作
                self.api.close()  # 取消注释这行，确保api正确关闭
                self.api = None
                self.tq_account = None
                self.connect_btn.setText("连接天勤账户")
                self.capital_input.clear()
                
                # 移除旧连接方式，直接调用connect_tq
                self.connect_btn.clicked.disconnect()
                self.connect_btn.clicked.connect(self.connect_tq)
                
                QMessageBox.information(self, "断开成功", "已断开天勤账户连接")
        except Exception as e:
            QMessageBox.critical(self, "断开错误", f"断开连接时发生错误: {str(e)}")



    def closeEvent(self, event): 
        """重写关闭事件"""
        if self.api:
            reply = QMessageBox.question(self, "确认", "是否断开天勤账户连接？",
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if reply == QMessageBox.Yes:
                self.api.close()  # 确保在程序退出前关闭API
                self.api = None
        if hasattr(self, 'strategy_thread') and self.strategy_thread.is_alive():
            if self.api:
                self.api.close()
            self.strategy_thread.join(timeout=1)
        
        # 根据操作系统选择正确的进程名称
        if self.process_id is None:
            print("关闭策略")
            if platform.system() == 'Windows':
                process_name = "auto_stp10_stable04_03.exe"
            else:
                process_name = "auto_stp10_stable04_01"
            self.terminate_external_program(process_name)
        event.accept()

    # 添加全局设置页面索引
    # 如果需要新增左侧按钮或者新增右侧页面，在PAGE_INDEX中添加，在init_ui中添加对应的页面。

    PAGE_INDEX = {
        "CALCULATE": 0,
        "ORDER": 1,
        "PRODUCT_MGMT": 2,
        "GLOBAL_SETTINGS": 3,  # 新增全局设置页面索引
        "AUTO_SL": 4,
        "HELP": 5   
    }
    
    # +++ 新增初始化数据方法 +++
    def init_data(self):
        """初始化核心数据"""
        # 连接成功后加载监控品种
        conn = connect_db()
        if conn:
            # 获取监控中的品种（is_monitored=1）
            self.products = [
                {
                    'name': p[1],
                    'margin': p[3],
                    'stoploss': p[4],
                    'exchange_code': p[2],
                    'limit_stoploss': p[7]
                } 
                for p in get_monitored_products(conn)
                if p[6]  # 第7个字段是is_monitored
            ]
            conn.close()
        else:
            self.products = []
        
        self.api = None      # 天勤API连接实例
        self.account = None  # 交易账户信息

    def init_ui(self):
        # ==== 主布局 ====
        main_widget = QWidget()
        main_h_layout = QHBoxLayout(main_widget)
        
        # ==== 左侧面板 ====
        side_panel = self._init_side_panel()
        
        # ==== 右侧堆叠窗口 ====
        self.stacked_widget = QStackedWidget()
        # 统一使用 addWidget 按顺序添加
        self.stacked_widget.addWidget(self._init_capital_ui())          # 索引0
        self.stacked_widget.addWidget(self._init_order_ui())            # 索引1
        self.stacked_widget.addWidget(self._init_product_management_ui()) # 索引2
        self.stacked_widget.addWidget(self._init_global_settings_ui())          #索引3
        self.stacked_widget.addWidget(self._init_auto_sl_ui())          # 索引4
        self.stacked_widget.addWidget(self._init_help_ui())             # 索引5
        
        main_h_layout.addWidget(side_panel)
        main_h_layout.addWidget(self.stacked_widget, stretch=1)
        self.setCentralWidget(main_widget)

    def _init_side_panel(self):
        """统一初始化侧边栏"""
        panel = QWidget()
        layout = QVBoxLayout(panel)
        
        # 新增按钮组初始化
        self.nav_btns = QButtonGroup(self)
        self.nav_btns.setExclusive(True)  # 确保按钮互斥

        button_config = [
            ("计算下单量", self.PAGE_INDEX["CALCULATE"]),
            ("下单", self.PAGE_INDEX["ORDER"]),
            ("品种管理", self.PAGE_INDEX["PRODUCT_MGMT"]),
            ("全局设置", self.PAGE_INDEX["GLOBAL_SETTINGS"]),  # 新增全局设置按钮
            ("启动策略交易", self.PAGE_INDEX["AUTO_SL"]),
            ("帮助中心", self.PAGE_INDEX["HELP"])
        ]
        
        # 确保 PAGE_INDEX 与实际索引一致
        self.PAGE_INDEX = {
            "CALCULATE": 0,
            "ORDER": 1,
            "PRODUCT_MGMT": 2,
            "GLOBAL_SETTINGS": 3,
            "AUTO_SL": 4,
            "HELP": 5
        }

        self.side_buttons = []
        for idx, (text, page_id) in enumerate(button_config):
            btn = QPushButton(text)
            btn.setCheckable(True)
            btn.setMinimumSize(200, 40)
            # 更新为经典立体样式
            btn.setStyleSheet("""
                QPushButton {
                    text-align: center;
                    padding: 12px 25px;
                    border: 1px solid #a0a0a0;
                    border-radius: 4px;
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                        stop:0 #f6f7fa, stop:1 #e0e1e5);
                    font: 13px "微软雅黑";  /* 移除默认粗体 */
                    color: #505050;
                }
                QPushButton:checked, QPushButton:pressed {
                    font-weight: bold;  /* 仅在选中/按下时加粗 */
                }
                QPushButton:hover {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                        stop:0 #e3e7ef, stop:1 #d4d7dc);
                }
                QPushButton:checked {
                    background: #e3f2fd;
                    border: 1px solid #2196F3;
                    color: #1565C0;
                }
                QPushButton:pressed {
                    background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                        stop:0 #d0d0d0, stop:1 #e0e0e0);
                }
            """)
            btn.clicked.connect(lambda _, x=page_id: self.stacked_widget.setCurrentIndex(x))
            layout.addWidget(btn)
            self.side_buttons.append(btn)
            self.nav_btns.addButton(btn, idx)

        # 设置默认选中第一个按钮
        self.side_buttons[0].setChecked(True)  # 新增默认选中

        layout.addStretch()
        return panel

    # 新增页面切换方法
    def switch_page(self, button):
        """处理导航按钮点击"""
        index = self.nav_btns.id(button)
        self.stacked_widget.setCurrentIndex(index)

    def setup_connections(self):
        """统一信号连接"""
        self.connect_btn.clicked.connect(self.connect_tq)
        self.update_signal.connect(lambda x: self.capital_input.setText(x))
        self.connection_signal.connect(self.handle_connection)
        self.nav_btns.buttonClicked.connect(self.switch_page)
        self.stacked_widget.currentChanged.connect(self.handle_page_change)

    def handle_page_change(self, index):
        """处理页面切换事件"""
        try:
            if index == 0:  # 资金页面
                # 添加空值检查
                # if hasattr(self, 'account') and self.account is not None:
                #     self.capital_input.setText(f"{self.account.balance:.2f}")

                if self.api and self.account:
                    self.capital_input.setText(f"{self.account.balance:.2f}")
                elif not self.api and not self.account:
                    self.capital_input.setText("未连接账户")
            elif index == 3:  # 自动止盈止损页面
                pass  # 可添加刷新逻辑
        except Exception as e:
            QMessageBox.warning(self, "警告", f"页面刷新失败: {str(e)}")

    # ==== 统一页面初始化模式 ====
    def _init_capital_ui(self):
        """资金管理页面"""
        capital_widget = QWidget()
        layout = QVBoxLayout(capital_widget)
        layout.setContentsMargins(15, 15, 15, 15)
        
        # 恢复资金管理界面原有的UI组件
        self.connect_btn = QPushButton("连接天勤账户")
        self.connect_btn.clicked.connect(self.connect_tq)
        layout.addWidget(self.connect_btn)
        
        # 输入区域
        input_layout = QHBoxLayout()
        self.capital_input = QLineEdit()
        self.capital_input.setPlaceholderText("正在获取账户资金...")
        self.capital_input.setReadOnly(True)
        input_layout.addWidget(QLabel("账户可用资金:"))
        input_layout.addWidget(self.capital_input)
        
        self.risk_input = QLineEdit()
        self.risk_input.setPlaceholderText("输入风险比例（%）")
        self.risk_input.setText("20")
        input_layout.addWidget(QLabel("风险比例:"))
        input_layout.addWidget(self.risk_input)
        layout.addLayout(input_layout)
        
        # 计算按钮
        self.calc_btn = QPushButton("计算下单量")
        self.calc_btn.clicked.connect(self.calculate)
        layout.addWidget(self.calc_btn)
        
        # 表格
        self.table = QTableWidget()
        self.table.setColumnCount(5)
        self.table.setHorizontalHeaderLabels(["品种", "保证金", "止损点数", "建议开仓量", "最大开仓量"])
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        # 启用按表头排序功能
        self.table.setSortingEnabled(True)
        layout.addWidget(self.table)

        # +++ 新增公式说明 +++
        formula_label = QLabel("""
            <div style='margin:15px 0; color:#666; font-size:12px;'>
                <b>计算公式说明：</b>
                <ul>
                    <li>风险资金 = 账户资金 × 风险比例</li>
                    <li>建议开仓量 = 风险资金 ÷ (保证金 × 3)</li>
                    <li>最大开仓量 = 风险资金 ÷ 保证金</li>
                    <li>止损金额 = 止损点数 × 合约乘数 × 价格单位</li>
                </ul>
                <div style='color:#2196F3;'>注：建议开仓量采用1/3仓位原则，最大开仓量表示当前风险承受下的极限仓位</div>
            </div>
        """)
        formula_label.setWordWrap(True)
        layout.addWidget(formula_label)

        # 删除这行 ↓
        # self.stacked_widget.addWidget(capital_widget)
        return capital_widget  # 新增返回语句

    def calculate(self):  

        """执行资金计���逻辑"""
        try:
            # 添加输入验证
            if not self.capital_input.text() or float(self.capital_input.text()) <= 0:
                raise ValueError("请先连接账户并获取有效资金数据")
                
            # 获取输入值（添加类型转换）
            risk_percent = float(self.risk_input.text().strip('%'))  # 支持带%的输入
            capital = float(self.capital_input.text())
            
            if risk_percent <= 0 or risk_percent > 100:
                raise ValueError("风险比例需在 0-100% 之间")
                
            # 清空表格
            self.table.setRowCount(0)

            # 重新查询数据库获取监控品种
            conn = connect_db()
            if conn:
                self.products = [
                    {
                        'name': p[1],
                        'margin': p[3],
                        'stoploss': p[4],
                        'exchange_code': p[2],
                        'limit_stoploss': p[7]
                    } 
                    for p in get_monitored_products(conn)
                    if p[6]  # 第7个字段是is_monitored
                ]
                conn.close()
            else:
                self.products = []

            # 计算每个品种的开仓量
            # 添加风险资金计算
            risk_capital = capital * risk_percent / 100
            if risk_capital <= 0:
                raise ValueError("风险资金必须大于0")
            
            # 清空表格（添加加载状态提示）
            self.table.setRowCount(0)
            if not self.products:
                raise ValueError("没有需要计算的监控品种，请先在品种管理中添加")
            
            # 计算每个品种的开仓量（添加浮点数处理）
            for product in self.products:
                margin = float(product['margin'])
                stoploss = float(product['stoploss'])
                
                # 核心计算公式
                max_lots = risk_capital / margin
                suggested_lots = int(max_lots // 3)
                
                # 添加表格行（格式化数字显示）
                row = self.table.rowCount()
                self.table.insertRow(row)
                
                self.table.setItem(row, 0, QTableWidgetItem(product['name']))
                self.table.setItem(row, 1, QTableWidgetItem(f"{margin:.2f}"))
                self.table.setItem(row, 2, QTableWidgetItem(f"{stoploss:.1f}")) 
                self.table.setItem(row, 3, QTableWidgetItem(str(suggested_lots)))
                self.table.setItem(row, 4, QTableWidgetItem(f"{max_lots:.1f}"))
                
        except ValueError as e:
            QMessageBox.warning(self, "输入错误", str(e))
        except Exception as e:
            QMessageBox.critical(self, "计算错误", f"发生未知错误: {str(e)}")


    def _init_order_ui(self): 
        """订单页面（原 init_order_ui 修改）"""
        order_widget = QWidget()
        layout = QVBoxLayout(order_widget)
        layout.setContentsMargins(15, 15, 15, 15)
        
        # 从数据库获取监控品种
        conn = connect_db()
        monitored_products = []
        if conn:
            monitored_products = get_monitored_products(conn)  # 现在可以正确调用
            conn.close()
        else:
            monitored_products = []
        
        # 添加订单界面基础组件
        self.symbol_combo = QComboBox()
        self.symbol_combo.addItems([p[1] for p in monitored_products])  # 使用数据库中的名称
        
        self.quantity_input = QLineEdit("1")  # 设置默认数量为1
        
        # 创建三个操作按钮
        btn_layout = QHBoxLayout()
        buy_btn = QPushButton("买进")
        sell_btn = QPushButton("卖出") 
        close_btn = QPushButton("平仓")
        
        # 绑定不同操作类型
        buy_btn.clicked.connect(lambda: self.submit_order("BUY", "OPEN"))
        sell_btn.clicked.connect(lambda: self.submit_order("SELL", "OPEN"))
        close_btn.clicked.connect(lambda: self.submit_order("", "CLOSE"))
        
        btn_layout.addWidget(buy_btn)
        btn_layout.addWidget(sell_btn)
        btn_layout.addWidget(close_btn)
        
        form_layout = QFormLayout()
        form_layout.addRow("选择品种:", self.symbol_combo)
        form_layout.addRow("下单数量:", self.quantity_input)
        
        layout.addLayout(form_layout)
        layout.addLayout(btn_layout)
        layout.addStretch()
        
        # 删除这行 ↓
        # self.stacked_widget.insertWidget(1, order_widget)
        return order_widget  # 确保返回

    def submit_order(self, direction, offset):
        """处理订单提交"""
        try:
            # 获取选择的交易所代码
            conn = connect_db()
            monitored_products = get_monitored_products(conn) if conn else []
            selected = monitored_products[self.symbol_combo.currentIndex()]
            exchange_code = selected[2]  # 获取交易所代码
            
            quantity = int(self.quantity_input.text())
            
            if not self.api:
                raise RuntimeError("请先连接天勤账户")
                
            # 特殊处理平仓指令
            if offset == "CLOSE":
                direction = "CLOSE_ALL"  # 自定义平仓指令
                
            # 创建订单（需根据实际API调整）
            order = self.api.insert_order(
                symbol=exchange_code,
                direction=direction if offset != "CLOSE" else "SELL",
                offset=offset,
                volume=quantity
            )
            
            action = "买进" if direction == "BUY" else "卖出"
            action = "平仓" if offset == "CLOSE" else action
            QMessageBox.information(self, "下单成功", f"已提交{exchange_code} {quantity}手{action}指令")
            
        except Exception as e:
            QMessageBox.critical(self, "错误", f"操作失败: {str(e)}")


    def _init_product_management_ui(self):
        """品种管理页面"""
        self.changed_items=set()
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(10, 10, 10, 10)  # 减小边距
        
        # 创建表格控件
        self.product_table = QTableWidget()
        # 启用按表头排序功能
        self.product_table.setSortingEnabled(True)
        # 设置表格可编辑
        self.product_table.setEditTriggers(QTableWidget.AllEditTriggers)
        # 添加回车键事件处理
        self.product_table.keyPressEvent = self.handle_product_table_key_event
        # 添加移动止盈止损周期列
        self.product_table.setColumnCount(9)
        self.product_table.setHorizontalHeaderLabels(["品种名称", "交易所代码", "保证金", "止损点数", "止盈点数", "限额止损", "移动止盈止损周期","开仓方向","是否监控", ])
        self.product_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 自动拉伸列宽
        self.product_table.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)  # 新增：表头左对齐
        self.product_table.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)  # 新增：尺寸策略
        
        # 设置表格样式
        self.product_table.verticalHeader().setDefaultSectionSize(30)  # 行高统一为30px
        self.product_table.setShowGrid(False)  # 隐藏网格线
        self.product_table.setAlternatingRowColors(True)  # 启用交替行颜色

        # 关键：连接 itemChanged 信号到 on_item_changed 方法
        self.product_table.itemChanged.connect(self.on_item_changed)

        # 修改按钮组布局
        btn_layout = QHBoxLayout()
        # +++ 调整按钮顺序 +++
        refresh_btn = QPushButton("刷新")
        add_btn = QPushButton("添加品种")
        edit_btn = QPushButton("编辑品种")
        del_btn = QPushButton("删除品种")
        save_btn = QPushButton("保存修改")  # 新增保存按钮
        # 确保连接正确的保存方法
        save_btn.clicked.connect(self.save_product_changes_new)  

        # 设置按钮属性
        for btn in [add_btn, edit_btn, del_btn]:
            btn.setMinimumWidth(100)
            btn.setMinimumHeight(30)
        
        # 绑定事件
        add_btn.clicked.connect(self._show_add_product_dialog)
        edit_btn.clicked.connect(self._show_edit_dialog)
        del_btn.clicked.connect(self._delete_selected_product)
        
        # 添加按钮到布局
        btn_layout.addWidget(refresh_btn)  # 第一个按钮
        btn_layout.addWidget(add_btn)
        btn_layout.addWidget(edit_btn)
        btn_layout.addWidget(del_btn)
        btn_layout.addWidget(save_btn)  # 添加保存按钮
        # --- 按钮创建结束 ---
        
        # 调整布局比例（按钮组:表格 = 1:9）
        layout.addLayout(btn_layout, stretch=1)
        layout.addWidget(self.product_table, stretch=9)  # 设置拉伸因子
        
        # 初始化表格数据
        self._refresh_product_table()
        return widget

    def handle_product_table_key_event(self, event):
        """处理品种表格的按键事件"""
        if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
            # 调用专门的策略保存方法
            self.save_product_changes_new()
            QMessageBox.information(self, "成功", "修改已保存")
        else:
            # 调用原始的keyPressEvent处理其他按键
            QTableWidget.keyPressEvent(self.product_table, event)

    def save_strategy_changes_new(self):
        """新的保存策略表格的修改到数据库的函数"""
        try:
            conn = connect_db()
            for row in range(self.strategy_table.rowCount()):
                product_id = self.strategy_table.item(row, 0).data(Qt.UserRole)
                if not product_id:
                    continue

                name = self.strategy_table.item(row, 0).text()
                exchange_code = self.strategy_table.item(row, 1).text()
                margin = float(self.strategy_table.item(row, 2).text())
                stoploss = float(self.strategy_table.item(row, 3).text())
                takeprofit_text = self.strategy_table.item(row, 4).text()
                takeprofit = float(takeprofit_text) if takeprofit_text else 0
                limit_stoploss = float(self.strategy_table.item(row, 5).text())
                mtp = int(self.strategy_table.item(row, 6).text())
                dks = self.strategy_table.item(row, 7).text()
                is_monitored = 1 if self.strategy_table.item(row, 8).text() == "是" else 0

                data = {
                    'name': name,
                    'exchange_code': exchange_code,
                    'margin': margin,
                    'stoploss': stoploss,
                    'takeprofit': takeprofit,
                    'limit_stoploss': limit_stoploss,
                    'mtp': mtp,
                    'dks': dks,
                    'is_monitored': is_monitored
                }
                update_product(conn, product_id, data)
            conn.commit()
            conn.close()
        except Exception as e:
            QMessageBox.critical(self, "错误", f"保存失败: {str(e)}")

    def on_item_changed(self, item):
        """处理表格项变化事件"""
        row = item.row()
        self.changed_items.add(row)
        # print(f"Row {row} has been changed. Changed rows: {self.changed_items}")  # 添加日志输出

    def save_product_changes_new(self):
        """新的保存品种表格的修改到数据库的函数"""
        print("调用：save_product_changes_new函数")
        try:
            conn = connect_db()
            print(f"Changed rows: {self.changed_items}")  # 打印修改行
            for row in sorted(self.changed_items):
                product_id_item = self.product_table.item(row, 0)
                if product_id_item is None or product_id_item.data(Qt.UserRole) is None:
                    print(f"Skipping row {row} because product_id is None.")
                    continue
                product_id = product_id_item.data(Qt.UserRole)

                name_item = self.product_table.item(row, 0)
                exchange_code_item = self.product_table.item(row, 1)
                margin_item = self.product_table.item(row, 2)
                stoploss_item = self.product_table.item(row, 3)
                takeprofit_item = self.product_table.item(row, 4)
                limit_stoploss_item = self.product_table.item(row, 5)
                mtp_item = self.product_table.item(row, 6)
                dks_item = self.product_table.item(row, 7)
                is_monitored_item = self.product_table.item(row, 8)

                # 检查每个单元格是否为 None
                if any(item is None for item in [name_item, exchange_code_item, margin_item, stoploss_item, takeprofit_item, limit_stoploss_item, mtp_item, dks_item, is_monitored_item]):
                    print(f"Skipping row {row} because some cells are None.")
                    continue

                name = name_item.text()
                exchange_code = exchange_code_item.text()
                margin = float(margin_item.text())
                stoploss = float(stoploss_item.text())
                takeprofit_text = takeprofit_item.text()
                takeprofit = float(takeprofit_text) if takeprofit_text else 0
                limit_stoploss = float(limit_stoploss_item.text())
                mtp = int(mtp_item.text())
                dks = dks_item.text()
                is_monitored = 1 if is_monitored_item.text() == "是" else 0

                data = {
                    'name': name,
                    'exchange_code': exchange_code,
                    'margin': margin,
                    'stoploss': stoploss,
                    'takeprofit': takeprofit,
                    'limit_stoploss': limit_stoploss,
                    'mtp': mtp,
                    'dks': dks,
                    'is_monitored': is_monitored
                }
                print(f"Updating product with ID {product_id}: {data}")  # 打印更新数据
                update_product(conn, product_id, data)
            conn.commit()
            conn.close()
            self.changed_items.clear()  # 清空记录
            self._refresh_product_table()
            QMessageBox.information(self, "成功", "修改已保存")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"保存失败: {str(e)}")

    # 新增类方法定义（必须位于类内部）
    def _refresh_product_table(self):
        """刷新品种表格数据"""
        conn = connect_db()
        if conn:
            products = get_all_products(conn)
            self.product_table.setRowCount(len(products))
            
            for row, product in enumerate(products):
                self.product_table.setItem(row, 0, QTableWidgetItem(product[1]))
                self.product_table.setItem(row, 1, QTableWidgetItem(product[2]))
                self.product_table.setItem(row, 2, QTableWidgetItem(str(product[3])))
                self.product_table.setItem(row, 3, QTableWidgetItem(f"{product[4]:.1f}"))  # 止损显示1位小数
                self.product_table.setItem(row, 4, QTableWidgetItem(f"{product[5]:.1f}"))  # 止盈显示1位小数
                try:
                    # 尝试将限额止损字段（索引为 6）转换为浮点数
                    limit_stoploss = float(product[6])
                    self.product_table.setItem(row, 5, QTableWidgetItem(f"{limit_stoploss:.2f}"))
                except ValueError:
                    # 转换失败时，直接显示原始值
                    self.product_table.setItem(row, 5, QTableWidgetItem(product[6]))
                self.product_table.setItem(row, 6, QTableWidgetItem(str(product[7])))  # 显示移动止盈止损周期
                self.product_table.setItem(row, 7, QTableWidgetItem(str(product[8])))  # 显示交易方向
                self.product_table.setItem(row, 8, QTableWidgetItem("是" if product[9] else "否")) 
                self.product_table.item(row, 0).setData(Qt.UserRole, product[0])  # 存储数据库ID
            conn.close()

    def _show_add_product_dialog(self):
        """显示添加品种对话框"""
        dialog = QDialog(self)
        dialog.setWindowTitle("添加新品种")
        layout = QFormLayout(dialog)  # 创建新的布局
        
        # 创建输入控件
        name_edit = QLineEdit()
        code_edit = QLineEdit()
        margin_edit = QLineEdit()
        stoploss_edit = QLineEdit()
        takeprofit_edit = QLineEdit()
        limit_stoploss_edit = QLineEdit()
        monitor_combo = QComboBox()
        mtp_edit = QLineEdit("5")  # 默认值为 5

        dks_combo = QComboBox()
        # 修改：添加 "不开仓仅止损" 选项
        dks_combo.addItems(["双向", "只做多", "只做空", "不开仓仅止损"])
        dks_combo.setCurrentText("双向")  # 默认值为 双向

        monitor_combo.addItems(["是", "否"])

        
        # 添加控件到布局
        layout.addRow("品种名称:", name_edit)
        layout.addRow("交易所代码:", code_edit)
        layout.addRow("保证金:", margin_edit)
        layout.addRow("止损点数:", stoploss_edit)
        layout.addRow("止盈点数:", takeprofit_edit)
        layout.addRow("限额止损:", limit_stoploss_edit)
        layout.addRow("移动止盈止损周期:", mtp_edit)  # 新增输入框
        layout.addRow("开仓方向:", dks_combo)  # 新增输入框
        layout.addRow("是否监控:", monitor_combo)

        
        # 添加按钮
        btn_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        btn_box.accepted.connect(lambda: self._save_new_product(
            dialog,
            name_edit.text(),
            code_edit.text(),
            margin_edit.text(),
            stoploss_edit.text(),
            takeprofit_edit.text(),
            limit_stoploss_edit.text(),
            mtp_edit.text(),  # 新增参数
            dks_combo.currentText(),  # 新增参数
            monitor_combo.currentText()
   
        ))
        btn_box.rejected.connect(dialog.reject)
        
        layout.addWidget(btn_box)
        dialog.exec_()

    def _save_new_product(self, dialog, name, code, margin, stoploss, takeprofit, limit_stoploss, mtp, dks, monitor):
        """添加新品种到数据库"""
        print("添加新品种到数据库")
        try:
            conn = connect_db()
        except Exception as e:
            QMessageBox.critical(self, "错误", f"数据库连接失败: {str(e)}")
            return
        try:
            margin_val = float(margin)
            stoploss_val = float(stoploss)
            limit_stoploss_val = float(limit_stoploss)
            mtp_val = int(mtp)
            dks_val=str(dks)
            # 处理止盈点数为空的情况
            takeprofit_value = float(takeprofit) if takeprofit else 0
            insert_product(conn, (
                name,
                code,
                margin_val,
                stoploss_val,
                takeprofit_value,               
                limit_stoploss_val,
                mtp_val,  # 新增 mtp 值
                dks_val,  # 新增 dks 值
                1 if monitor == "是" else 0  # 确保正确设置 is_monitored
            ))
            conn.commit()
            conn.close()
            self._refresh_product_table()
            dialog.accept()
        except Exception as e:
            QMessageBox.critical(self, "错误", f"数据库插入失败: {str(e)}")
            if conn:
                conn.close()

    def _show_edit_dialog(self):
        """显示编辑对话框（完整实现）"""
        selected_row = self.product_table.currentRow()
        if selected_row == -1:
            return
        
        # 获取原始数据
        product_id = self.product_table.item(selected_row, 0).data(Qt.UserRole)
        conn = connect_db()
        product = get_product_by_id(conn, product_id)
        conn.close()

        # 检查 product 是否为 None
        if product is None:
            QMessageBox.warning(self, "错误", "未找到对应的品种记录，请刷新表格后重试。")
            return
        
        # 创建编辑对话框
        dialog = QDialog(self)
        dialog.setWindowTitle("编辑品种")
        layout = QFormLayout(dialog)
        
        # 初始化输入框并填充数据（修复变量名错误）
        name_edit = QLineEdit(product[1])
        code_edit = QLineEdit(product[2])
        margin_edit = QLineEdit(str(product[3]))
        stoploss_edit = QLineEdit(f"{product[4]:.1f}")
        takeprofit_edit = QLineEdit(f"{product[5]:.1f}" if product[5] else "")
        try:
            # 尝试将限额止损字段转换为浮点数
            limit_stoploss = float(product[6])
            limit_stoploss_edit = QLineEdit(f"{limit_stoploss:.2f}")
        except ValueError:
            # 转换失败时，直接使用原始字符串
            limit_stoploss_edit = QLineEdit(product[6])

        mtp_edit = QLineEdit(str(product[7]))  # 初始化移动止盈止损周期
        
        dks_combo = QComboBox()
        # 修改：添加 "不开仓仅止损" 选项
        dks_combo.addItems(["双向", "只做多", "只做空", "不开仓仅止损"])
        # 修改：判断 dks_value 时增加 "不开仓仅止损"
        dks_value = product[8] if product[8] in ["双向", "只做多", "只做空", "不开仓仅止损"] else "双向"
        dks_combo.setCurrentText(dks_value)

        monitor_check = QComboBox()
        monitor_check.addItems(["是", "否"])
        monitor_check.setCurrentIndex(0 if product[9] else 1)
   
        
        # 添加输入框到布局（修复乱码字段名）
        layout.addRow("品种名称:", name_edit)
        layout.addRow("交易所代码:", code_edit)
        layout.addRow("保证金:", margin_edit)
        layout.addRow("止损点数:", stoploss_edit)
        layout.addRow("止盈点数:", takeprofit_edit)
        layout.addRow("限额止损:", limit_stoploss_edit)
        layout.addRow("移动止盈止损周期:", mtp_edit)  # 新增输入框
        # 新增显示控制交易方向的下拉列表
        layout.addRow("开仓方向:", dks_combo)
        layout.addRow("是否监控:", monitor_check)
        
        # 添加对话框按钮
        btn_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        btn_box.accepted.connect(lambda: self._save_edit(
            dialog, product_id, {
                'name': name_edit.text(),
                'exchange_code': code_edit.text(),
                'margin': margin_edit.text(),
                'stoploss': stoploss_edit.text(),
                'takeprofit': takeprofit_edit.text(),
                'limit_stoploss': limit_stoploss_edit.text(),
                'mtp': mtp_edit.text(),  # 新增字段
                'dks': dks_combo.currentText(),  # 新增字段
                'is_monitored': monitor_check.currentText()

            }
        ))
        btn_box.rejected.connect(dialog.reject)
        
        layout.addWidget(btn_box)
        dialog.exec_()

    def _save_edit(self, dialog, product_id, updates):
        """保存修改到数据库"""
        try:
            conn = connect_db()
            # 处理止盈点数为空的情况
            takeprofit_value = float(updates['takeprofit']) if updates['takeprofit'] else 0
            # 转换数据类型（修复字段类型）
            data = {
                'name': updates['name'],
                'exchange_code': updates['exchange_code'],
                'margin': float(updates['margin']),
                'stoploss': float(updates['stoploss']),
                'takeprofit': takeprofit_value,
                'limit_stoploss': float(updates['limit_stoploss']),
                'mtp': int(updates['mtp']),   # 新增 mtp 字段
                'dks': updates['dks'],  # 新增 dks 字段
                'is_monitored': 1 if updates['is_monitored'] == "是" else 0 # 确保正确设置 is_monitored

            }
            update_product(conn, product_id, data)
            conn.commit()
            conn.close()
            self._refresh_product_table()
            dialog.accept()
            QMessageBox.information(self, "成功", "修改已保存")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"保存失败: {str(e)}")

    def _delete_selected_product(self):
            """删除选中品种（修复版）"""
            selected_row = self.product_table.currentRow()
            if selected_row == -1:
                return
            
            # 获取数据库ID（关键修复）
            product_id = self.product_table.item(selected_row, 0).data(Qt.UserRole)
            product_name = self.product_table.item(selected_row, 0).text()
            
            reply = QMessageBox.question(
                self, "确认删除", 
                f"确定要删除 {product_name} 吗？",
                QMessageBox.Yes | QMessageBox.No
            )
            
            if reply == QMessageBox.Yes:
                try:
                    conn = connect_db()
                    # 使用新的删除方法
                    delete_product_by_name(conn, product_name)
                    conn.commit()
                    conn.close()
                    self._refresh_product_table()
                except Exception as e:
                    QMessageBox.critical(self, "错误", f"删除失败: {str(e)}")

    #品种管理页面按下Enter键的事件函数
    def handle_product_table_key_event(self, event):
        """处理品种表格的按键事件"""
        if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
            # 保存配置并刷新
            self.save_product_changes_new()
            self._refresh_product_table()
        else:
            # 调用原始的keyPressEvent处理其他按键
            QTableWidget.keyPressEvent(self.product_table, event)

    def _refresh_strategy_table(self):
            """从数据库刷新策略表格数据，复用品种管理的刷新逻辑"""
            conn = connect_db()
            if conn:
                products = get_monitored_products(conn)
                self.strategy_table.setColumnCount(9)  # 确保列数正确
                self.strategy_table.setHorizontalHeaderLabels(["品种名称", "交易所代码", "保证金", "止损点数", "止盈点数", "限额止损", "移动止盈止损周期","开仓方向", "是否监控"])
                self.strategy_table.setRowCount(len(products))
                
                for row, product in enumerate(products):
                    try:
                        self.strategy_table.setItem(row, 0, QTableWidgetItem(product[1]))
                        self.strategy_table.setItem(row, 1, QTableWidgetItem(product[2]))
                        self.strategy_table.setItem(row, 2, QTableWidgetItem(str(product[3])))
                        self.strategy_table.setItem(row, 3, QTableWidgetItem(f"{product[4]:.1f}"))
                        self.strategy_table.setItem(row, 4, QTableWidgetItem(f"{product[5]:.1f}"))
                        try:
                            limit_stoploss = float(product[6])
                            self.strategy_table.setItem(row, 5, QTableWidgetItem(f"{limit_stoploss:.2f}"))
                        except ValueError:
                            self.strategy_table.setItem(row, 5, QTableWidgetItem(str(product[6])))
                        self.strategy_table.setItem(row, 6, QTableWidgetItem(str(product[7])))  # 显示移动止盈止损周期
                        self.strategy_table.setItem(row, 7, QTableWidgetItem(product[8]))  # 显示开仓方向
                        self.strategy_table.setItem(row, 8, QTableWidgetItem("是" if product[9] else "否"))
                    except IndexError as e:
                        print(f"填充表格时出错，行 {row}，错误信息: {e}")  # 添加错误处理
                conn.close()


    #全局设置页面
    def _refresh_config_table(self):
        """刷新配置表格数据"""
        try:
            conn = sqlite3.connect('trade_monitor.db')
            cursor = conn.cursor()
            cursor.execute("SELECT key, value ,description FROM config")
            configs = cursor.fetchall()
            self.config_table.setRowCount(len(configs))
            for row, (key, value,description) in enumerate(configs):
                self.config_table.setItem(row, 0, QTableWidgetItem(key))
                item = QTableWidgetItem(str(value))
                self.config_table.setItem(row, 1, item)
                self.config_table.setItem(row, 2, QTableWidgetItem(description))
            conn.close()
        except Exception as e:
            QMessageBox.critical(self, "错误", f"获取配置信息失败: {str(e)}")

    def _save_configs(self):
        """保存配置信息到数据库"""
        try:
            # 添加保存确认对话框
            reply = QMessageBox.question(
                self, 
                "确认保存",
                "配置项的值已经更改，是否保存？",
                QMessageBox.Yes | QMessageBox.No,
                QMessageBox.No
            )
            
            if reply == QMessageBox.No:
                return
                
            conn = sqlite3.connect('trade_monitor.db')
            cursor = conn.cursor()
            for row in range(self.config_table.rowCount()):
                key = self.config_table.item(row, 0).text()
                value = self.config_table.item(row, 1).text()
                cursor.execute("UPDATE config SET value = ? WHERE key = ?", (value, key))
            conn.commit()
            conn.close()
            QMessageBox.information(self, "成功", "配置保存成功")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"保存配置信息失败: {str(e)}")

    def handle_config_table_key_event(self, event):
        """处理配置表格的按键事件"""
        if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
            # 保存配置并刷新
            self._save_configs()
            self._refresh_config_table()
            #QMessageBox.information(self, "成功", "配置已自动保存并刷新")
        else:
            # 调用原始的keyPressEvent处理其他按键
            QTableWidget.keyPressEvent(self.config_table, event)

    def _init_global_settings_ui(self):
        """全局设置页面初始化"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(10, 10, 10, 10)  # 减小边距与品种管理页面一致

        # 创建按钮布局
        btn_layout = QHBoxLayout()
        btn_layout.setAlignment(Qt.AlignLeft)
        btn_layout.setSpacing(10)
        
        # 创建按钮 - 样式与品种管理页面一致
        refresh_btn = QPushButton("刷新")
        save_btn = QPushButton("保存")

        
        # 设置按钮属性
        for btn in [refresh_btn, save_btn]:
            btn.setMinimumWidth(300)
            btn.setMinimumHeight(30)
        
        # 绑定事件
        refresh_btn.clicked.connect(self._refresh_config_table)
        save_btn.clicked.connect(self._save_configs)
        
        # 添加按钮到布局
        btn_layout.addWidget(refresh_btn)
        btn_layout.addWidget(save_btn)
        
        # 创建表格控件 - 样式与品种管理页面一致
        self.config_table = QTableWidget()
        self.config_table.setColumnCount(3)
        self.config_table.setHorizontalHeaderLabels(["配置项", "值","含义"])
        
        # 添加回车键事件处理
        self.config_table.keyPressEvent = self.handle_config_table_key_event
        self.config_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.config_table.setSortingEnabled(True)
        
        # 设置表格样式
        self.config_table.verticalHeader().setDefaultSectionSize(30)  # 行高统一为30px
        self.config_table.setShowGrid(False)  # 隐藏网格线
        self.config_table.setAlternatingRowColors(True)  # 启用交替行颜色
        self.config_table.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)  # 表头左对齐
        # 修改表格列宽设置
        self.config_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 所有列都拉伸填充
        self.config_table.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)  # 新增：尺寸策略
        
        # 设置表格编辑策略
        self.config_table.setEditTriggers(QTableWidget.AllEditTriggers)
        for row in range(self.config_table.rowCount()):
            self.config_table.item(row, 0).setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
            self.config_table.item(row, 2).setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)

        # 初始化数据
        self._refresh_config_table()

        # 添加控件到主布局
        layout.addLayout(btn_layout)
        layout.addWidget(self.config_table)

        # 添加提示文字
        tip_label = QLabel("""
            <div style='margin:15px 0; color:#2196F3; font-size:12px;'>
                注：修改好后，按Enter键，自动保存！
            </div>
        """)
        tip_label.setWordWrap(True)
        layout.addWidget(tip_label)

        return widget



    #启动策略交易页面中，启动策略开仓，启动策略平仓调用的函数，以后要增加策略就在这两个函数中增加
    def toggle_strategy_open(self, strategy_type):
        """
        切换策略开仓状态
        参数：
            strategy_type: 策略类型字符串（当前版本固定为"OPEN"）
        功能：
            1. 控制策略开仓按钮的文本切换
            2. 管理策略启动/停止状态
        注意事项：
            - 按钮的选中状态通过isChecked()获取
            - 实际策略逻辑待后续实现
        """
    
        # 根据按钮选中状态更新界面显示
        if self.start_open_btn .isChecked():
            self.start_open_btn.setText(f"已启动策略{strategy_type} (单击停止)")  # 运行中状态显示
            print("启动策略开仓")
            # TODO: 此处添加实际启动策略的逻辑（例如创建策略线程）
        else:
            self.start_open_btn.setText(f"启动策略{strategy_type}")  # 默认状态显示
            print("已停止策略开仓")
            # TODO: 此处添加停止策略的逻辑（例如终止策略线程）
    


    class WorkerThread(QThread):
        finished_signal = pyqtSignal(bool)
        
        def __init__(self, exe_path, parent=None):
            super().__init__(parent)
            self.exe_path = exe_path
            self.process = None
            
        def run(self):
            try:
                # 根据操作系统选择不同的启动方式
                if platform.system() == 'Windows':
                    self.process = subprocess.Popen(
                        [self.exe_path],
                        cwd=os.path.dirname(self.exe_path),
                        creationflags=subprocess.CREATE_NEW_CONSOLE
                    )
                else:  # Linux或其他系统
                    self.process = subprocess.Popen(
                        [self.exe_path],
                        cwd=os.path.dirname(self.exe_path)
                    )
                time.sleep(1)  # 等待程序启动
                
                # 只在Windows系统下尝试最小化窗口
                if platform.system() == 'Windows':
                    self.minimize_exe_window()
                    
                self.finished_signal.emit(True)
            except Exception as e:
                print(f"线程执行出错: {str(e)}")
                self.finished_signal.emit(False)
                
        def minimize_exe_window(self):
            """最小化外部程序窗口 (仅Windows系统)"""
            if platform.system() != 'Windows' or not self.process:
                return
                
            # 导入Windows特有的库
            try:
                import win32gui
                import win32con
                import win32process
                
                start_time = time.time()
                while time.time() - start_time < 5:
                    try:
                        def callback(hwnd, extra):
                            if win32gui.IsWindowVisible(hwnd):
                                _, pid = win32process.GetWindowThreadProcessId(hwnd)
                                if pid == self.process.pid:
                                    win32gui.ShowWindow(hwnd, win32con.SW_MINIMIZE)
                                    return False
                            return True
                        win32gui.EnumWindows(callback, None)
                        break
                    except:
                        time.sleep(0.5)
            except ImportError:
                print("Windows特有库导入失败，跳过窗口最小化")
                pass

    def on_thread_finished(self, success):
        #self.start_stp_close_btn.setEnabled(True)
        if success:
            self.process_id = self.worker_thread.process.pid

        else:
            QMessageBox.critical(self, "错误", "启动外部程序失败")

    def terminate_external_program(self,ExeName):
        try:
            # 使用 psutil 库 - 跨平台方式终止进程
            for proc in psutil.process_iter(['name']):
                if proc.info['name'] == ExeName:
                    proc.terminate()
                    gone, still_alive = psutil.wait_procs([proc], timeout=5)
                    if still_alive:
                        for p in still_alive:
                            p.kill()
            print(f"使用 psutil 尝试终止 {ExeName}")
            
            # 在Linux上，可能需要使用不同的方法查找进程
            if platform.system() != 'Windows':
                try:
                    # 使用pgrep查找进程，然后终止
                    cmd = f"pgrep -f {ExeName}"
                    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, text=True)
                    if result.returncode == 0:
                        pids = result.stdout.strip().split('')
                        for pid in pids:
                            if pid:
                                kill_cmd = f"kill -9 {pid}"
                                subprocess.run(kill_cmd, shell=True)
                                print(f"在Linux上终止进程 {pid}")
                except Exception as linux_err:
                    print(f"Linux终止进程失败: {linux_err}")
                    
        except Exception as e:
            print(f"使用 psutil 终止 {ExeName} 失败: {e}")

        self.process_id = None
        


    #单击策略止损平仓按钮
    def toggle_strategy_stp_close(self, strategy_type):
        """切换策略状态"""   
        print("启动 自动止盈止损")
        btn_open_close = self.start_stp_close_btn 
    
        if btn_open_close.isChecked():
            if self.process_id is None:
                script_dir = os.path.dirname(os.path.abspath(__file__))
                
                # 根据操作系统选择正确的可执行文件名
                if platform.system() == 'Windows':
                    exe_name = "auto_stp10_stable04_03.exe"
                else:  # Linux或其他系统
                    exe_name = "auto_stp10_stable04_01"  # Linux上通常不带.exe后缀
                
                self.exe_path = os.path.join(script_dir, exe_name)
            
            if not os.path.exists(self.exe_path):
                # 如果找不到可执行文件，尝试查找其他可能的名称
                if platform.system() != 'Windows':
                    alternative_paths = [
                        os.path.join(script_dir, "auto_stp10_stable04_01"),
                        os.path.join(script_dir, "auto_stp10_stable04_01.py"),
                        os.path.join(script_dir, "auto_stp10_stable04_01.sh")
                    ]
                    for alt_path in alternative_paths:
                        if os.path.exists(alt_path):
                            self.exe_path = alt_path
                            # 如果是脚本文件，确保它是可执行的
                            if alt_path.endswith('.py') or alt_path.endswith('.sh'):
                                try:
                                    os.chmod(alt_path, 0o755)  # 添加执行权限
                                except:
                                    pass
                            break
                
                # 如果仍然找不到可执行文件，显示错误
                if not os.path.exists(self.exe_path):
                    QMessageBox.critical(self, "错误", f"未找到程序: {self.exe_path}")
                    btn_open_close.setChecked(False)  # 恢复按钮状态
                    return
                
            btn_open_close.setEnabled(False)  # 禁用按钮防止重复点击
            self.worker_thread = self.WorkerThread(self.exe_path)
            self.worker_thread.finished_signal.connect(self.on_thread_finished)
            self.worker_thread.start()
            self.start_stp_close_btn.setText("正在启动 自动止盈止损")
            time.sleep(3)
            self.start_stp_close_btn.setEnabled(True)
            self.start_stp_close_btn.setText("停止 自动止盈止损")
        else:
            print("停止自动止盈止损")
            # 根据操作系统选择正确的进程名称
            if platform.system() == 'Windows':
                process_name = "auto_stp10_stable04_03.exe"
            else:
                process_name = "auto_stp10_stable04_01"
            self.terminate_external_program(process_name)
            self.start_stp_close_btn.setText("启动 自动止盈止损")


    def _init_auto_sl_ui(self):
        """策略交易页面初始化"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(15, 15, 15, 15)
        
        # +++ 新增刷新按钮布局 +++
        btn_layout = QHBoxLayout()
        refresh_btn = QPushButton("刷新数据")
        refresh_btn.clicked.connect(self._refresh_strategy_table)  # 确保连接正确
        save_btn = QPushButton("保存修改")  # 新增保存按钮
        save_btn.clicked.connect(self._save_strategy_changes)  # 绑定保存事件
        btn_layout.addWidget(refresh_btn)
        btn_layout.addWidget(save_btn)  # 添加保存按钮

        # 表格控件初始化
        self.strategy_table = QTableWidget()
        # 添加移动止盈止损周期列
        self.strategy_table.setColumnCount(9)
        self.strategy_table.setHorizontalHeaderLabels(["品种名称", "交易所代码", "保证金", "止损点数", "止盈点数", "限额止损", "移动止盈止损周期", "开仓方向", "是否监控"])
        self.strategy_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        # 启用按表头排序功能
        self.strategy_table.setSortingEnabled(True)
        # 设置表格可编辑
        self.strategy_table.setEditTriggers(QTableWidget.AllEditTriggers)
        # 添加回车键事件处理
        self.strategy_table.keyPressEvent = self.handle_strategy_table_key_event


        # 初始化数据
        self._refresh_strategy_table()
        
        # 控制按钮区域（原有代码保持不变）
        control_layout = QVBoxLayout()
        
        # 策略开仓组
        open_group = QHBoxLayout()
        self.start_open_btn = QPushButton("启动策略开仓")
        self.start_open_btn.setCheckable(True)
        # 修改按钮样式（保持原有样式但移除不支持的属性）
        self.start_open_btn.setStyleSheet("""
            QPushButton {
                background-color: #f8f9fa;
                border: 1px solid #ced4da;
                border-radius: 4px;
                padding: 5px 10px;
                min-width: 120px;
            }
            QPushButton:checked {
                background-color: #dc3545;
                color: white;
                border-color: #dc3545;
            }
        """)
        
        # 策略平仓组
        close_group = QHBoxLayout()
        self.start_close_btn = QPushButton("启动策略平仓")
        self.start_close_btn.setCheckable(True)
        self.start_close_btn.setStyleSheet(self.start_open_btn.styleSheet())  # 复用相同样式 

        # 策略平仓组
        open_close_group = QHBoxLayout()
        self.start_stp_close_btn = QPushButton("启动 自动止盈止损")
        self.start_stp_close_btn.setCheckable(True)
        self.start_stp_close_btn.setStyleSheet(self.start_open_btn.styleSheet())  # 复用相同样式 

        # 下单量输入框
        self.open_qty = QLineEdit("1")
        self.open_qty.setValidator(QIntValidator(1, 1000))
        self.open_qty.setMaximumWidth(100)
        self.open_qty.setAlignment(Qt.AlignLeft)  # 左对齐
        
        # 调整布局结构
        open_group.addWidget(self.start_open_btn)
        open_group.addWidget(QLabel("下单量:"))
        open_group.addWidget(self.open_qty)
        open_group.addWidget(self.start_close_btn)  # 平仓按钮放到输入框右侧
        open_group.addWidget(self.start_stp_close_btn)
        open_group.addStretch()
        
        
        # 事件绑定需要统一
        self.start_open_btn.clicked.connect(lambda: self.toggle_strategy_open(" OPEN "))
        self.start_close_btn.clicked.connect(lambda: self.toggle_strategy_close(" CLOSE "))  # 改为统一的调用方式
        self.start_stp_close_btn.clicked.connect(lambda: self.toggle_strategy_stp_close(" STP || CLOSE "))  # 改为统一的调用方式
        
        # 组合布局
        control_layout.addLayout(open_group)
        control_layout.addLayout(close_group)
        control_layout.addLayout(open_close_group)
        # 关键修正：调整布局顺序
        layout.addLayout(btn_layout)  # 添加按钮布局
        layout.addWidget(self.strategy_table)
        layout.addLayout(control_layout)
        
        return widget

    def handle_strategy_table_key_event(self, event):
        """处理策略表格的按键事件"""
        if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
            # 保存配置并刷新
            self._save_strategy_changes()
        else:
            # 调用原始的keyPressEvent处理其他按键
            QTableWidget.keyPressEvent(self.strategy_table, event)

    def _save_strategy_changes(self):
        """保存策略表格的修改到数据库"""
        try:
            conn = connect_db()
            for row in range(self.strategy_table.rowCount()):
                product_id = self.strategy_table.item(row, 0).data(Qt.UserRole)
                name = self.strategy_table.item(row, 0).text()
                exchange_code = self.strategy_table.item(row, 1).text()
                margin = float(self.strategy_table.item(row, 2).text())
                stoploss = float(self.strategy_table.item(row, 3).text())
                takeprofit = self.strategy_table.item(row, 4).text()
                limit_stoploss = float(self.strategy_table.item(row, 5).text())
                mtp = int(self.strategy_table.item(row, 6).text())
                dks = self.strategy_table.item(row, 7).text()
                is_monitored = 1 if self.strategy_table.item(row, 8).text() == "是" else 0

                # 处理止盈点数为空的情况
                takeprofit_value = float(takeprofit) if takeprofit else 0

                data = {
                    'name': name,
                    'exchange_code': exchange_code,
                    'margin': margin,
                    'stoploss': stoploss,
                    'takeprofit': takeprofit_value,
                    'limit_stoploss': limit_stoploss,
                    'mtp': mtp,
                    'dks': dks,
                    'is_monitored': is_monitored
                }
                update_product(conn, product_id, data)
            conn.commit()
            conn.close()
            self._refresh_strategy_table()
            QMessageBox.information(self, "成功", "修改已保存")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"保存失败: {str(e)}")

    def _init_help_ui(self):
        """帮助中心页面初始化"""
        help_widget = QWidget()
        layout = QVBoxLayout(help_widget)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(5)  # 设置最小间距为5像素

        # 帮助文本部分 - 使用更紧凑的HTML样式
        help_text = QLabel("""
            <div style="margin:0 0 0 20px;">
                <h2 style="margin:0 0 2px 0; font-size:16px;">帮助中心</h2>
                <p style="margin:2px 0 2px 0; font-size:12px;">📌 使用指南：</p>
                <ul style="margin:2px 0 2px 15px; padding-left:5px; font-size:12px;">
                    <li style="margin-bottom:2px;">品种管理：添加/修改监控的期货品种参数</li>
                    <li style="margin-bottom:2px;">自动止盈止损：设置自动化的交易策略</li>
                    <li style="margin-bottom:2px;">账户连接：绑定天勤账户获取实时资金数据</li>
                </ul>
                <p style="margin:20px 0 0 0; font-size:12px;">🆘 技术支持：
                    <a href="https://qm.qq.com/q/933538038" style="margin-right:50px;">QQ群：933538038</a>
                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                    <a href="mailto:wg3k@foxmail.com?subject=技术支持请求&body=请在此输入您的问题">Email:wg3k@foxmail.com</a>
                </p>
            </div>
        """)
        help_text.setAlignment(Qt.AlignLeft)
        help_text.setWordWrap(True)
        layout.addWidget(help_text)

        # 图片部分 - 直接添加，不使用ScrollArea
        img_label = QLabel()
        pixmap = QPixmap("img/beauty02.png")
        if not pixmap.isNull():
            pixmap = pixmap.scaled(400, 500, Qt.KeepAspectRatio, Qt.SmoothTransformation)
            img_label.setPixmap(pixmap)
            img_label.setStyleSheet("""
                QLabel {
                    margin-left: 20px;
                    margin-top: 5px;
                    background: transparent;
                }
            """)
            # 阴影效果
            shadow = QGraphicsDropShadowEffect()
            shadow.setBlurRadius(10)  # 减小阴影半径
            shadow.setOffset(3, 3)    # 减小阴影偏移
            shadow.setColor(QColor(0, 0, 0, 40))  # 降低阴影透明度
            img_label.setGraphicsEffect(shadow)
        else:
            img_label.setText("图片加载失败")

        layout.addWidget(img_label, alignment=Qt.AlignLeft|Qt.AlignTop)
        layout.addStretch(1)  # 添加弹性空间保持顶部对齐

        return help_widget


if __name__ == "__main__":
    # 移除重复的 os 导入（已合并到文件顶部）
    # 新增的禁用PNG警告设置保持不变
    os.environ["QT_LOGGING_RULES"] = "qt.png.warning=false"
    
    app = QApplication(sys.argv)
    # 根据操作系统选择适当的样式
    if platform.system() == 'Windows':
        app.setStyle(QStyleFactory.create("WindowsVista"))
        app.setFont(QFont("微软雅黑", 9))
    else:
        # Linux上使用Fusion样式，它在大多数Linux发行版上看起来都不错
        app.setStyle(QStyleFactory.create("Fusion"))
        app.setFont(QFont("文泉驿微米黑", 9))  # Linux上常用的中文字体
    app.setStyleSheet("""
        * {
            font-family: "微软雅黑", "Consolas";
            font-size: 10pt;
        }
        QTableWidget {
            background-color: white;
            border: 1px solid #E0E0E0;
            margin-top: 10px;
        }
        /* 移除特定控件的字体设置 */
        QLineEdit, QTableWidget, QLabel {
            min-height: 25px;
            padding: 2px 5px;
        }
        QTableWidget {
            min-width: 800px;
        }
        QLineEdit {
            min-width: 150px;
        }
        QComboBox {
            min-width: 200px;
        }
    """)
    app.setWindowIcon(QIcon('app.png'))
    window = CapitalManager()
    window.show()
    sys.exit(app.exec_())